﻿using System;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Convertor.Base;
using zijian666.Converts.Core;
using zijian666.Converts.Extensions;

namespace zijian666.Converts.Convertor;

/// <summary>
///  <seealso cref="Enum"/> 枚举类型转换器
/// </summary>
public class EnumConvertor<T> : FromConvertor<T>,
    IFrom<string, T>,
    IFrom<IConvertible, T>
{
    /// <inheritdoc/>
    public ConvertResult<T> From(IConvertContext context, string input)
    {
        if (string.IsNullOrWhiteSpace(input))
        {
            return context.ConvertFail(this, input);
        }
        try
        {
            return (T)Enum.Parse(OutputType, input, true);
        }
        catch (Exception ex)
        {
            return ex;
        }
    }

    /// <inheritdoc/>
    public ConvertResult<T> From(IConvertContext context, IConvertible input)
        => input.GetTypeCode() switch
        {
            TypeCode.Empty or TypeCode.DBNull or TypeCode.DateTime or TypeCode.Boolean => context.ConvertFail(this, input),
            TypeCode.Decimal or TypeCode.Char or TypeCode.Int16 or TypeCode.Int32 or TypeCode.Int64 or TypeCode.SByte or TypeCode.Double or TypeCode.Single => (T)Enum.ToObject(OutputType, input.ToInt64(null)),
            TypeCode.Byte or TypeCode.UInt16 or TypeCode.UInt32 or TypeCode.UInt64 => (T)Enum.ToObject(OutputType, input.ToUInt64(null)),
            TypeCode.String => From(context, input.ToString(null)),
            _ => context.ConvertFail(this, input),
        };
}
